package com.lanyun.aicorrectassistant.domain.studentAssignments.impl;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.OSSObject;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lanyun.aicorrectassistant.basic.bean.Result;
import com.lanyun.aicorrectassistant.basic.entity.AssignmentTemplates;
import com.lanyun.aicorrectassistant.basic.entity.AuthUser;
import com.lanyun.aicorrectassistant.basic.entity.GradingResults;
import com.lanyun.aicorrectassistant.basic.entity.StudentAssignments;
import com.lanyun.aicorrectassistant.basic.service.AssignmentTemplatesService;
import com.lanyun.aicorrectassistant.basic.service.AuthUserService;
import com.lanyun.aicorrectassistant.basic.service.GradingResultsService;
import com.lanyun.aicorrectassistant.basic.service.StudentAssignmentsService;
import com.lanyun.aicorrectassistant.config.StorageConfig;
import com.lanyun.aicorrectassistant.context.LoginContextHolder;
import com.lanyun.aicorrectassistant.controller.admin.gradingResults.vo.ErrorDetail;
import com.lanyun.aicorrectassistant.controller.admin.gradingResults.vo.GradingResult;
import com.lanyun.aicorrectassistant.controller.admin.studentAssignments.vo.StudentAssignmentsRequestPageVO;
import com.lanyun.aicorrectassistant.controller.admin.studentAssignments.vo.StudentAssignmentsRequestVO;
import com.lanyun.aicorrectassistant.controller.admin.studentAssignments.vo.StudentAssignmentsResponseVO;
import com.lanyun.aicorrectassistant.convert.StudentAssignmentsConvert;
import com.lanyun.aicorrectassistant.domain.studentAssignments.StudentAssignmentsDomainService;
import com.lanyun.aicorrectassistant.basic.bean.PageResult;
import com.lanyun.aicorrectassistant.enums.AssignmentEnum;
import com.lanyun.aicorrectassistant.enums.IsDeletedFlagEnum;
import com.lanyun.aicorrectassistant.enums.RoleTypeEnum;
import dev.langchain4j.model.chat.ChatLanguageModel;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 学生作业表领域服务实现
 *
 * @author makejava
 * @version 1.0
 * @date 2025-05-12 01:54:23
 */
@Service
@Slf4j
public class StudentAssignmentsDomainServiceImpl implements StudentAssignmentsDomainService {

    @Resource
    private StudentAssignmentsService studentAssignmentsService;

    @Resource
    private AssignmentTemplatesService assignmentTemplatesService;

    @Resource
    private GradingResultsService gradingResultsService;

    @Resource
    private ChatLanguageModel chatModel;

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private OSS ossClient;

    @Resource
    private StorageConfig storageConfig;

    @Resource
    private AuthUserService authUserService;

    @Override
    public PageResult<StudentAssignmentsResponseVO> page(StudentAssignmentsRequestPageVO requestPageVO) {
        PageResult<StudentAssignmentsResponseVO> pageResult = new PageResult<>();
        StudentAssignments queryEntity = StudentAssignmentsConvert.INSTANCE.convert(requestPageVO);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        String role = LoginContextHolder.getRole();
        if (RoleTypeEnum.STUDENT.getRole().equals(role)) {
            queryEntity.setStudentId(Long.valueOf(LoginContextHolder.getLoginId()));
        }
        List<StudentAssignments> entities = studentAssignmentsService.page(queryEntity,
                requestPageVO.getStart(), requestPageVO.getPageSize());

        if (entities.isEmpty()) {
            return pageResult;
        }

        Long count = studentAssignmentsService.count(queryEntity);
        List<StudentAssignmentsResponseVO> vos = StudentAssignmentsConvert.INSTANCE.convertEntityToRespList(entities);

        vos.forEach(v -> {
            AuthUser authUser = authUserService.queryById(v.getStudentId());
            v.setStudentName(authUser.getRealName());
            AssignmentTemplates assignmentTemplates = assignmentTemplatesService.queryById(v.getTemplateId());
            v.setAssignmentTitle(assignmentTemplates.getTitle());
            v.setFilePathForTeacher(assignmentTemplates.getFilePath());
        });

        pageResult.setResult(vos);
        pageResult.setTotal(count.intValue());
        return pageResult;
    }

    @Override
    public Boolean update(StudentAssignmentsRequestVO requestVO) {
        StudentAssignments entity = StudentAssignmentsConvert.INSTANCE.convert(requestVO);
        return studentAssignmentsService.update(entity) != 0;
    }

    @Override
    public Boolean delete(Long id) {
        StudentAssignments entity = new StudentAssignments();
        entity.setId(id);
        entity.setIsDeleted(IsDeletedFlagEnum.DELETED.getVal());
        return studentAssignmentsService.update(entity) != 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insert(StudentAssignmentsRequestVO requestVO) throws Exception {
        // 验证模板有效性
        validateTemplate(requestVO.getTemplateId());

        // 保存学生作业记录
        StudentAssignments assignment = StudentAssignments.builder()
                .templateId(requestVO.getTemplateId())
                .studentId(Long.valueOf(LoginContextHolder.getLoginId()))
                .filePath(requestVO.getFilePath())
                .status(AssignmentEnum.PENDING.getCode())
                .build();
        studentAssignmentsService.insert(assignment);
    }

    @Transactional(rollbackFor = Exception.class)
//    public Boolean saveGradingResult(StudentAssignmentsRequestVO requestVO) {
//        StudentAssignments studentAssignments = studentAssignmentsService.queryById(requestVO.getId());
//        if (studentAssignments == null) {
//            return false;
//        }
//        try {
//
//            AssignmentTemplates template = validateTemplate(studentAssignments.getTemplateId());
//
//            // 读取作业内容
//            String content = readAssignmentContent(studentAssignments.getFilePath());
//
//            // 构建完整提示词
//            String fullPrompt = buildFullPrompt(template, content);
//
//            // 调用AI批改
//            String aiResponse = invokeAIModel(fullPrompt);
//
//            // 保存批改结果
//            GradingResults gradingResults = new GradingResults();
//            gradingResults.setRawResponse(aiResponse);
//            gradingResultsService.insert(gradingResults);
//
//            studentAssignments.setGradeTime(new Date());
//            studentAssignments.setStatus(AssignmentEnum.COMPLETED.getCode());
//        } catch (Exception e) {
//            studentAssignments.setStatus(AssignmentEnum.ERROR.getCode());
//        } finally {
//            int updateCount = studentAssignmentsService.update(studentAssignments);
//            return updateCount != 0;
//        }
//    }
    // 修改返回类型为流式响应（如 Spring WebFlux 的 Flux）
    public Flux<String> saveGradingResult(StudentAssignmentsRequestVO requestVO) {
        return Flux.create(sink -> {
            try {
                StudentAssignments assignment = studentAssignmentsService.queryById(requestVO.getId());
                if (assignment == null) {
                    sink.error(new IllegalArgumentException("作业不存在"));
                    return;
                }

                AssignmentTemplates template = validateTemplate(assignment.getTemplateId());
                String content = readAssignmentContent(assignment.getFilePath());
                String fullPrompt = buildFullPrompt(template, content);

                // 流式调用 AI 模型
//                Stream<AiChunk> aiStream = chatModel.streamingChat(fullPrompt);
//
//                aiStream.subscribe(
//                        chunk -> {
//                            // 实时发送思考过程或结果片段
//                            String chunkText = chunk.text();
//                            if (chunkText.contains("思考过程")) {
//                                sink.next("思考过程: " + extractThinkingProcess(chunkText));
//                            } else {
//                                sink.next("批改结果: " + chunkText);
//                            }
//                        },
//                        error -> {
//                            assignment.setStatus(AssignmentEnum.ERROR.getCode());
//                            studentAssignmentsService.update(assignment);
//                            sink.error(error);
//                        },
//                        () -> {
//                            assignment.setStatus(AssignmentEnum.COMPLETED.getCode());
//                            studentAssignmentsService.update(assignment);
//                            sink.complete();
//                        }
//                );
            } catch (Exception e) {
                sink.error(e);
            }
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean submitGrading(Long id, String gradingResult) {
        StudentAssignments studentAssignments = studentAssignmentsService.queryById(id);
        try {
            studentAssignments.setStatus(AssignmentEnum.COMPLETED.getCode());
            GradingResults gradingResults = new GradingResults();
            gradingResults.setAssignmentId(id);
            gradingResults.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
            gradingResults.setRawResponse(gradingResult);
            gradingResultsService.insert(gradingResults);
        } catch (Exception e) {
            studentAssignments.setStatus(AssignmentEnum.ERROR.getCode());
            return false;
        } finally {
            return studentAssignmentsService.update(studentAssignments) != 0;
        }
    }

    // 提示词优化：强制分阶段输出
    private String buildFullPrompt(AssignmentTemplates template, String content) {
        return template.getAiPromptTemplate()
                + "\n【需批改的文档内容】\n" + content
                + "\n\n请按以下步骤处理并严格分阶段响应："
                + "\n1. 先输出你的完整思考过程（标记为 '### 思考过程'）"
                + "\n2. 最后输出批改结果（标记为 '### 批改结果'）";
    }

    private String invokeAIModel(String prompt) {
        try {
            return chatModel.chat(prompt);
        } catch (Exception e) {
            throw new RuntimeException("作业批改服务暂不可用");
        }
    }

    private String serializeErrors(List<ErrorDetail> errors) {
        try {
            return objectMapper.writeValueAsString(errors);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("错题数据序列化失败");
        }
    }

    private GradingResult parseAIResponse(String rawResponse) {
        try {
            // 预处理响应内容
            String jsonContent = cleanJsonResponse(rawResponse);

            // JSON解析器
            ObjectMapper objectMapper = new ObjectMapper()
                    .enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES)
                    .enable(JsonParser.Feature.IGNORE_UNDEFINED)
                    .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

            // 安全解析JSON
            JsonNode root = objectMapper.readTree(jsonContent);

            //  防御性字段提取
            return extractGradingResult(root, rawResponse);
        } catch (Exception e) {
            throw new RuntimeException("AI响应格式异常：" + e.getMessage());
        }
    }

    private String cleanJsonResponse(String dirtyJson) {
        // 匹配所有可能的JSON代码块
        Pattern pattern = Pattern.compile("```(json)?(.*?)```", Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(dirtyJson);

        // 提取第一个JSON代码块内容
        if (matcher.find()) {
            return matcher.group(2).trim();
        }

        // 无代码块时直接清理
        return dirtyJson.replaceAll("[`]", "")
                .replaceAll("(?i)json", "")
                .trim();
    }

    private GradingResult extractGradingResult(JsonNode root, String rawResponse) {
        // 使用安全路径获取字段
        int score = root.path("score").asInt(0);
        String accuracyText = root.path("accuracy").asText("0%");

        return GradingResult.builder()
                .rawResponse(rawResponse)
                .score(validateScore(score))
                .accuracy(parseAccuracy(accuracyText))
                .summary(root.path("summary").asText())
                .errorAnalysis(parseErrors(root.path("errors")))
                .build();
    }


    private List<ErrorDetail> parseErrors(JsonNode errorsNode) {
        List<ErrorDetail> errors = new ArrayList<>();
        errorsNode.forEach(node -> errors.add(new ErrorDetail(
                node.get("question_id").asText(),
                node.get("student_answer").asText(),
                node.get("correct_answer").asText(),
                node.get("knowledge_point").asText()
        )));
        return errors;
    }

    private int validateScore(int score) {
        if (score < 0 || score > 100) {
            throw new RuntimeException("分数值异常: " + score);
        }
        return score;
    }

    private BigDecimal parseAccuracy(String accuracyStr) {
        try {
            return new BigDecimal(accuracyStr.replace("%", ""))
                    .setScale(2, RoundingMode.HALF_UP);
        } catch (NumberFormatException e) {
            throw new RuntimeException("正确率格式错误: " + accuracyStr);
        }
    }


    private String readAssignmentContent(String filePath) throws Exception {
        String objectName = extractObjectName(filePath);

        try (OSSObject ossObject = ossClient.getObject(
                storageConfig.getAliyunOss().getBucketName(),
                objectName);
             InputStream contentStream = ossObject.getObjectContent();
             XWPFDocument document = new XWPFDocument(contentStream);
             XWPFWordExtractor extractor = new XWPFWordExtractor(document)) {

            return extractor.getText();
        } catch (IOException e) {
            throw new RuntimeException("作业文件读取失败", e);
        }

    }

    // URL解析优化
    private String extractObjectName(String url) throws UnsupportedEncodingException, URISyntaxException {
        String decodedUrl = URLDecoder.decode(url, StandardCharsets.UTF_8);
        URI uri = new URI(decodedUrl);
        String path = uri.getPath();
        return path.startsWith("/") ? path.substring(1) : path;
    }

    private AssignmentTemplates validateTemplate(Long templateId) {
        AssignmentTemplates template = assignmentTemplatesService.queryById(templateId);
        if (template == null) {
            throw new RuntimeException("无效的作业模板");
        }
        return template;
    }


    @Override
    public StudentAssignmentsResponseVO get(Long id) {
        StudentAssignments entity = studentAssignmentsService.queryById(id);
        StudentAssignmentsResponseVO studentAssignmentsResponseVO = StudentAssignmentsConvert.INSTANCE.convert(entity);
        if (studentAssignmentsResponseVO != null) {
            AuthUser authUser = authUserService.queryById(studentAssignmentsResponseVO.getStudentId());
            studentAssignmentsResponseVO.setStudentName(authUser.getRealName());
            AssignmentTemplates assignmentTemplates = assignmentTemplatesService.queryById(studentAssignmentsResponseVO.getTemplateId());
            studentAssignmentsResponseVO.setAssignmentTitle(assignmentTemplates.getTitle());
            studentAssignmentsResponseVO.setFilePathForTeacher(assignmentTemplates.getFilePath());
            if (studentAssignmentsResponseVO.getFilePath() != null &&
                    AssignmentEnum.COMPLETED.getCode().equals(studentAssignmentsResponseVO.getStatus())) {
                GradingResults queryEntity = new GradingResults();
                queryEntity.setAssignmentId(id);
                queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
                GradingResults gradingResults = gradingResultsService.queryByCondition(queryEntity);
                if (gradingResults != null) {
                    studentAssignmentsResponseVO.setGradingResult(gradingResults.getRawResponse());
//                    GradingResult gradingResult = new GradingResult();
//                    gradingResult.setAccuracy(gradingResults.getAccuracy());
//                    gradingResult.setScore(gradingResults.getScore());
//                    gradingResult.setSummary(gradingResults.getSummary());
//                    gradingResult.setRawResponse(gradingResults.getRawResponse());
//                    // 将错题结果转成数组
//                    List<ErrorDetail> errorDetailList = JSONUtil.toList(gradingResults.getErrorAnalysis().toString(), ErrorDetail.class);
//                    gradingResult.setErrorAnalysis(errorDetailList);
//                    studentAssignmentsResponseVO.setGradingResult(gradingResult);
                }
            }
        }
        return studentAssignmentsResponseVO;
    }
}
